/*
 * nwk_rx.c
 *
 *  Created on: Jul 12, 2013
 *      Author: Jonathan
 */

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "nwk.h"
#include "FreeRTOS.h"
#include "semphr.h"


nwk_packet_t nwk_rcv_queue[NWK_QUEUE_SIZE];
uint8_t rcv_queue_in;
uint8_t rcv_queue_out;

xSemaphoreHandle rx_mutex;

/* Local Prototypes */
uint8_t nwk_rx_init(void);
uint8_t nwk_receive_pkt_cb(void);
void nwk_process_pkt(void);
void nwk_process_pkt(void);

uint8_t nwk_rx_init(void)
{
	/* Initialize the queue pointers */
	rcv_queue_in = rcv_queue_out = 0;

	/* clear the nwk packets */
	memset(nwk_rcv_queue, 0, (sizeof(nwk_packet_t) * NWK_QUEUE_SIZE));

	rx_mutex = xSemaphoreCreateMutex();
	if(rx_mutex == NULL)
		return NWK_FAILURE;

	return NWK_SUCCESS;
}

static nwk_packet_t* nwk_rx_pkt_allocate(void)
{
	/* Make sure the rcv queue is not full */
	if((rcv_queue_in + 1) % NWK_QUEUE_SIZE == rcv_queue_out)
		return 0;

//	/* get the pointer for next empty spot to add at */
//	nwk_packet_t *new_pkt = nwk_rcv_queue + rcv_queue_in;

	/* modulus increment the add index */
	rcv_queue_in = (rcv_queue_in + 1) % NWK_QUEUE_SIZE;

	/* return the pointer */
	return (nwk_rcv_queue + rcv_queue_in);
}

/* The call back function for when the RX_DR interrupt is triggered */
uint8_t nwk_receive_pkt_cb(void)
{
	/* Get the meta information from the transceiver */
	//uint8_t rx_pipe = nrf24_getRxPipe(); //TODO2
	uint8_t rcvLength = nrf24_payloadLength();
	nwk_packet_t* rx_pkt;

	/* allocate a new packet on the receive queue */
	if(!( rx_pkt = nwk_rx_pkt_allocate() ))
		return NWK_QUEUE_FULL;//TODO2: overwrite the oldest packet rather than just returning??

	/* fill in the metadata and copy in the actual data */
	rx_pkt->data_len = rcvLength;
	//rx_pkt->dest_address = NWK__PIPE_TO_ADDRESS(rx_pipe); //TODO2:
	nrf24_getData(rx_pkt->data, rcvLength);

	/* Clear the RX_DR IRQ bit by writing to a 1 */
	nrf24_setBits_reg(STATUS, _BV(RX_DR));

	return NWK_SUCCESS;

	//TODO2:  b) see note c under register map table in nrf24 datasheet about checking fifo
}

bool nwk_rcv_queue_empty(void)
{
	return (rcv_queue_in == rcv_queue_out);
}

void nwk_process_pkt(void)
{
	nwk_packet_t rx_pkt = nwk_rcv_queue[rcv_queue_out];
	char debugSendString[3*33] = {0};
	for (uint8_t i = 0; i < rx_pkt.data_len; i++)
	{
		sprintf(debugSendString+(3*i), "%02X ", rx_pkt.data[i]);
	}
	printf("Rcv'd nwk pkt: %s\n", debugSendString);
	rcv_queue_out = (rcv_queue_out + 1) % NWK_QUEUE_SIZE;
}
